<!DOCTYPE HTML>
<html lang="en-US" >
    
    <head>
        
        <meta charset="UTF-8">
        <title>使用TCP | AKKA 2.3.6 Scala 文档</title>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="generator" content="GitBook 1.0.3">
        <meta name="HandheldFriendly" content="true"/>
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black">
        <link rel="apple-touch-icon-precomposed" sizes="152x152" href="../gitbook/images/apple-touch-icon-precomposed-152.png">
        <link rel="shortcut icon" href="../gitbook/images/favicon.ico" type="image/x-icon">
        
    
    
    
    <link rel="next" href="../chapter5/07_using_udp.html" />
    
    
    <link rel="prev" href="../chapter5/05_io.html" />
    

        
    </head>
    <body>
        
        
<link rel="stylesheet" href="../gitbook/style.css">


        
    <div class="book"  data-level="5.6" data-basepath=".." data-revision="1442802141200">
    

<div class="book-summary">
    <div class="book-search">
        <input type="text" placeholder="Type to search" class="form-control" />
    </div>
    <ul class="summary">
        
    	
    	
    	

        

        
    
        
        <li class="chapter " data-level="0" data-path="index.html">
            
                
                    <a href="../index.html">
                        <i class="fa fa-check"></i>
                        
                         Introduction
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="1" data-path="chapter1/introduction.html">
            
                
                    <a href="../chapter1/introduction.html">
                        <i class="fa fa-check"></i>
                        
                            <b>1.</b>
                        
                         引言
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="1.1" data-path="chapter1/01_what_is_akka.html">
            
                
                    <a href="../chapter1/01_what_is_akka.html">
                        <i class="fa fa-check"></i>
                        
                            <b>1.1.</b>
                        
                         Akka是什么?
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="1.2" data-path="chapter1/02_why_akka.html">
            
                
                    <a href="../chapter1/02_why_akka.html">
                        <i class="fa fa-check"></i>
                        
                            <b>1.2.</b>
                        
                         为什么使用Akka?
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="1.3" data-path="chapter1/03_getting_started.html">
            
                
                    <a href="../chapter1/03_getting_started.html">
                        <i class="fa fa-check"></i>
                        
                            <b>1.3.</b>
                        
                         入门
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="1.4" data-path="chapter1/04_the_obligatory_hello_world.html">
            
                
                    <a href="../chapter1/04_the_obligatory_hello_world.html">
                        <i class="fa fa-check"></i>
                        
                            <b>1.4.</b>
                        
                         必修的“Hello World”
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="1.5" data-path="chapter1/05_usecase_and_deployment_scenarios.html">
            
                
                    <a href="../chapter1/05_usecase_and_deployment_scenarios.html">
                        <i class="fa fa-check"></i>
                        
                            <b>1.5.</b>
                        
                         用例和部署场景
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="1.6" data-path="chapter1/06_examples_of_usecases_for_akka.html">
            
                
                    <a href="../chapter1/06_examples_of_usecases_for_akka.html">
                        <i class="fa fa-check"></i>
                        
                            <b>1.6.</b>
                        
                         Akka使用实例
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="2" data-path="chapter2/general.html">
            
                
                    <a href="../chapter2/general.html">
                        <i class="fa fa-check"></i>
                        
                            <b>2.</b>
                        
                         概述
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="2.1" data-path="chapter2/01_terminology_concepts.html">
            
                
                    <a href="../chapter2/01_terminology_concepts.html">
                        <i class="fa fa-check"></i>
                        
                            <b>2.1.</b>
                        
                         术语，概念
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="2.2" data-path="chapter2/02_actor_systems.html">
            
                
                    <a href="../chapter2/02_actor_systems.html">
                        <i class="fa fa-check"></i>
                        
                            <b>2.2.</b>
                        
                         Actor系统
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="2.3" data-path="chapter2/03_what_is_an_actor.html">
            
                
                    <a href="../chapter2/03_what_is_an_actor.html">
                        <i class="fa fa-check"></i>
                        
                            <b>2.3.</b>
                        
                         什么是Actor?
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="2.4" data-path="chapter2/04_supervision_and_monitoring.html">
            
                
                    <a href="../chapter2/04_supervision_and_monitoring.html">
                        <i class="fa fa-check"></i>
                        
                            <b>2.4.</b>
                        
                         监管与监控
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="2.5" data-path="chapter2/05_actor_references_paths_and_addresses.html">
            
                
                    <a href="../chapter2/05_actor_references_paths_and_addresses.html">
                        <i class="fa fa-check"></i>
                        
                            <b>2.5.</b>
                        
                         Actor引用, 路径与地址
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="2.6" data-path="chapter2/06_location_transparency.html">
            
                
                    <a href="../chapter2/06_location_transparency.html">
                        <i class="fa fa-check"></i>
                        
                            <b>2.6.</b>
                        
                         位置透明性
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="2.7" data-path="chapter2/07_akka_and_the_java_memory_model.html">
            
                
                    <a href="../chapter2/07_akka_and_the_java_memory_model.html">
                        <i class="fa fa-check"></i>
                        
                            <b>2.7.</b>
                        
                         Akka与Java内存模型
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="2.8" data-path="chapter2/08_message_delivery_reliability.html">
            
                
                    <a href="../chapter2/08_message_delivery_reliability.html">
                        <i class="fa fa-check"></i>
                        
                            <b>2.8.</b>
                        
                         消息发送语义
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="2.9" data-path="chapter2/09_configuration.html">
            
                
                    <a href="../chapter2/09_configuration.html">
                        <i class="fa fa-check"></i>
                        
                            <b>2.9.</b>
                        
                         配置
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="3" data-path="chapter3/actors.html">
            
                
                    <a href="../chapter3/actors.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.</b>
                        
                         Actors
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="3.1" data-path="chapter3/01_actors.html">
            
                
                    <a href="../chapter3/01_actors.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.1.</b>
                        
                         Actors
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="3.2" data-path="chapter3/02_typed_actors.html">
            
                
                    <a href="../chapter3/02_typed_actors.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.2.</b>
                        
                         有类型Actor
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="3.3" data-path="chapter3/03_fault_tolerance.html">
            
                
                    <a href="../chapter3/03_fault_tolerance.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.3.</b>
                        
                         容错
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="3.3.1" data-path="chapter3/03-1_fault_tolerance_sample.html">
            
                
                    <a href="../chapter3/03-1_fault_tolerance_sample.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.3.1.</b>
                        
                         容错示例
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="3.4" data-path="chapter3/04_dispatchers.html">
            
                
                    <a href="../chapter3/04_dispatchers.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.4.</b>
                        
                         调度器
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="3.5" data-path="chapter3/05_mailboxes.html">
            
                
                    <a href="../chapter3/05_mailboxes.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.5.</b>
                        
                         邮箱
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="3.6" data-path="chapter3/06_routing.html">
            
                
                    <a href="../chapter3/06_routing.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.6.</b>
                        
                         路由
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="3.7" data-path="chapter3/07_fsm.html">
            
                
                    <a href="../chapter3/07_fsm.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.7.</b>
                        
                         有限状态机(FSM)
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="3.8" data-path="chapter3/08_persistence.html">
            
                
                    <a href="../chapter3/08_persistence.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.8.</b>
                        
                         持久化
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="3.9" data-path="chapter3/09_testing_actor_systems.html">
            
                
                    <a href="../chapter3/09_testing_actor_systems.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.9.</b>
                        
                         测试Actor系统
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="3.9.1" data-path="chapter3/09_1_testkit-example.html">
            
                
                    <a href="../chapter3/09_1_testkit-example.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.9.1.</b>
                        
                         TestKit实例
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="3.10" data-path="chapter3/10_actor_dsl.html">
            
                
                    <a href="../chapter3/10_actor_dsl.html">
                        <i class="fa fa-check"></i>
                        
                            <b>3.10.</b>
                        
                         Actor DSL
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="4" data-path="chapter4/futures_and_agents.html">
            
                
                    <a href="../chapter4/futures_and_agents.html">
                        <i class="fa fa-check"></i>
                        
                            <b>4.</b>
                        
                         Futures与Agents
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="4.1" data-path="chapter4/01_futures.html">
            
                
                    <a href="../chapter4/01_futures.html">
                        <i class="fa fa-check"></i>
                        
                            <b>4.1.</b>
                        
                         Futures
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="4.2" data-path="chapter4/02_agents.html">
            
                
                    <a href="../chapter4/02_agents.html">
                        <i class="fa fa-check"></i>
                        
                            <b>4.2.</b>
                        
                         Agents
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="5" data-path="chapter5/networking.html">
            
                
                    <a href="../chapter5/networking.html">
                        <i class="fa fa-check"></i>
                        
                            <b>5.</b>
                        
                         网络
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="5.1" data-path="chapter5/01_cluster_cpecification.html">
            
                
                    <a href="../chapter5/01_cluster_cpecification.html">
                        <i class="fa fa-check"></i>
                        
                            <b>5.1.</b>
                        
                         集群规格
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="5.2" data-path="chapter5/02_cluster_usage.html">
            
                
                    <a href="../chapter5/02_cluster_usage.html">
                        <i class="fa fa-check"></i>
                        
                            <b>5.2.</b>
                        
                         集群用法
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="5.3" data-path="chapter5/03_remoting.html">
            
                
                    <a href="../chapter5/03_remoting.html">
                        <i class="fa fa-check"></i>
                        
                            <b>5.3.</b>
                        
                         远程
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="5.4" data-path="chapter5/04_serialization.html">
            
                
                    <a href="../chapter5/04_serialization.html">
                        <i class="fa fa-check"></i>
                        
                            <b>5.4.</b>
                        
                         序列化
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="5.5" data-path="chapter5/05_io.html">
            
                
                    <a href="../chapter5/05_io.html">
                        <i class="fa fa-check"></i>
                        
                            <b>5.5.</b>
                        
                         I/O
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter active" data-level="5.6" data-path="chapter5/06_using_tcp.html">
            
                
                    <a href="../chapter5/06_using_tcp.html">
                        <i class="fa fa-check"></i>
                        
                            <b>5.6.</b>
                        
                         使用TCP
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="5.7" data-path="chapter5/07_using_udp.html">
            
                
                    <a href="../chapter5/07_using_udp.html">
                        <i class="fa fa-check"></i>
                        
                            <b>5.7.</b>
                        
                         使用UDP
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="5.8" data-path="chapter5/08_zeromq.html">
            
                
                    <a href="../chapter5/08_zeromq.html">
                        <i class="fa fa-check"></i>
                        
                            <b>5.8.</b>
                        
                         ZeroMQ
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="5.9" data-path="chapter5/09_camel.html">
            
                
                    <a href="../chapter5/09_camel.html">
                        <i class="fa fa-check"></i>
                        
                            <b>5.9.</b>
                        
                         Camel
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="6" data-path="chapter6/utilities.html">
            
                
                    <a href="../chapter6/utilities.html">
                        <i class="fa fa-check"></i>
                        
                            <b>6.</b>
                        
                         实用工具
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="6.1" data-path="chapter6/01_event_bus.html">
            
                
                    <a href="../chapter6/01_event_bus.html">
                        <i class="fa fa-check"></i>
                        
                            <b>6.1.</b>
                        
                         事件总线
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="6.2" data-path="chapter6/02_logging.html">
            
                
                    <a href="../chapter6/02_logging.html">
                        <i class="fa fa-check"></i>
                        
                            <b>6.2.</b>
                        
                         日志
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="6.3" data-path="chapter6/03_scheduler.html">
            
                
                    <a href="../chapter6/03_scheduler.html">
                        <i class="fa fa-check"></i>
                        
                            <b>6.3.</b>
                        
                         调度器
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="6.4" data-path="chapter6/04_duration.html">
            
                
                    <a href="../chapter6/04_duration.html">
                        <i class="fa fa-check"></i>
                        
                            <b>6.4.</b>
                        
                         Duration
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="6.5" data-path="chapter6/05_circuit_breaker.html">
            
                
                    <a href="../chapter6/05_circuit_breaker.html">
                        <i class="fa fa-check"></i>
                        
                            <b>6.5.</b>
                        
                         线路断路器
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="6.6" data-path="chapter6/06_akka_extensions.html">
            
                
                    <a href="../chapter6/06_akka_extensions.html">
                        <i class="fa fa-check"></i>
                        
                            <b>6.6.</b>
                        
                         Akka扩展
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="6.7" data-path="chapter6/07_microkernel.html">
            
                
                    <a href="../chapter6/07_microkernel.html">
                        <i class="fa fa-check"></i>
                        
                            <b>6.7.</b>
                        
                         微内核
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="7" data-path="chapter7/howto_common_patterns.html">
            
                
                    <a href="../chapter7/howto_common_patterns.html">
                        <i class="fa fa-check"></i>
                        
                            <b>7.</b>
                        
                         如何使用：常用模式
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="8" data-path="chapter8/experimental_modules.html">
            
                
                    <a href="../chapter8/experimental_modules.html">
                        <i class="fa fa-check"></i>
                        
                            <b>8.</b>
                        
                         实验模块
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="8.1" data-path="chapter3/08_persistence.html">
            
                
                    <a href="../chapter3/08_persistence.html">
                        <i class="fa fa-check"></i>
                        
                            <b>8.1.</b>
                        
                         持久化
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="8.2" data-path="chapter8/02_multi_node_testing.html">
            
                
                    <a href="../chapter8/02_multi_node_testing.html">
                        <i class="fa fa-check"></i>
                        
                            <b>8.2.</b>
                        
                         多节点测试
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="8.3" data-path="chapter8/03_actors.html">
            
                
                    <a href="../chapter8/03_actors.html">
                        <i class="fa fa-check"></i>
                        
                            <b>8.3.</b>
                        
                         Actors(使用Java的Lambda支持)
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="8.4" data-path="chapter8/04_fsm.html">
            
                
                    <a href="../chapter8/04_fsm.html">
                        <i class="fa fa-check"></i>
                        
                            <b>8.4.</b>
                        
                         FSM(使用Java的Lambda支持)
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="8.5" data-path="chapter8/05_external_contributions.html">
            
                
                    <a href="../chapter8/05_external_contributions.html">
                        <i class="fa fa-check"></i>
                        
                            <b>8.5.</b>
                        
                         外部贡献
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="9" data-path="chapter9/information_for_akka_developers.html">
            
                
                    <a href="../chapter9/information_for_akka_developers.html">
                        <i class="fa fa-check"></i>
                        
                            <b>9.</b>
                        
                         Akka开发者信息
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="9.1" data-path="chapter9/01_building_akka.html">
            
                
                    <a href="../chapter9/01_building_akka.html">
                        <i class="fa fa-check"></i>
                        
                            <b>9.1.</b>
                        
                         构建Akka
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="9.2" data-path="chapter9/02_multi_jvm_testing.html">
            
                
                    <a href="../chapter9/02_multi_jvm_testing.html">
                        <i class="fa fa-check"></i>
                        
                            <b>9.2.</b>
                        
                         多JVM测试
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="9.3" data-path="chapter9/03_io_layer_design.html">
            
                
                    <a href="../chapter9/03_io_layer_design.html">
                        <i class="fa fa-check"></i>
                        
                            <b>9.3.</b>
                        
                         I/O层设计
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="9.4" data-path="chapter9/04_developer_guidelines.html">
            
                
                    <a href="../chapter9/04_developer_guidelines.html">
                        <i class="fa fa-check"></i>
                        
                            <b>9.4.</b>
                        
                         开发指南
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="9.5" data-path="chapter9/05_documentation_guidelines.html">
            
                
                    <a href="../chapter9/05_documentation_guidelines.html">
                        <i class="fa fa-check"></i>
                        
                            <b>9.5.</b>
                        
                         文档指南
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="9.6" data-path="chapter9/06_team.html">
            
                
                    <a href="../chapter9/06_team.html">
                        <i class="fa fa-check"></i>
                        
                            <b>9.6.</b>
                        
                         团队
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="10" data-path="chapter10/project_information.html">
            
                
                    <a href="../chapter10/project_information.html">
                        <i class="fa fa-check"></i>
                        
                            <b>10.</b>
                        
                         工程信息
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="10.1" data-path="chapter10/01_migration_guides.html">
            
                
                    <a href="../chapter10/01_migration_guides.html">
                        <i class="fa fa-check"></i>
                        
                            <b>10.1.</b>
                        
                         迁移指南
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="10.2" data-path="chapter10/02_issue_tracking.html">
            
                
                    <a href="../chapter10/02_issue_tracking.html">
                        <i class="fa fa-check"></i>
                        
                            <b>10.2.</b>
                        
                         问题追踪
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="10.3" data-path="chapter10/03_licenses.html">
            
                
                    <a href="../chapter10/03_licenses.html">
                        <i class="fa fa-check"></i>
                        
                            <b>10.3.</b>
                        
                         许可证
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="10.4" data-path="chapter10/04_sponsors.html">
            
                
                    <a href="../chapter10/04_sponsors.html">
                        <i class="fa fa-check"></i>
                        
                            <b>10.4.</b>
                        
                         赞助商
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="10.5" data-path="chapter10/05_project.html">
            
                
                    <a href="../chapter10/05_project.html">
                        <i class="fa fa-check"></i>
                        
                            <b>10.5.</b>
                        
                         项目
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    
        
        <li class="chapter " data-level="11" data-path="chapter11/additional_information.html">
            
                
                    <a href="../chapter11/additional_information.html">
                        <i class="fa fa-check"></i>
                        
                            <b>11.</b>
                        
                         附加信息
                    </a>
                
            
            
            <ul class="articles">
                
    
        
        <li class="chapter " data-level="11.1" data-path="chapter11/01_faq.html">
            
                
                    <a href="../chapter11/01_faq.html">
                        <i class="fa fa-check"></i>
                        
                            <b>11.1.</b>
                        
                         常见问题
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="11.2" data-path="chapter11/02_books.html">
            
                
                    <a href="../chapter11/02_books.html">
                        <i class="fa fa-check"></i>
                        
                            <b>11.2.</b>
                        
                         图书
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="11.3" data-path="chapter11/03_other_language_bindings.html">
            
                
                    <a href="../chapter11/03_other_language_bindings.html">
                        <i class="fa fa-check"></i>
                        
                            <b>11.3.</b>
                        
                         其他语言绑定
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="11.4" data-path="chapter11/04_akka_in_osgi.html">
            
                
                    <a href="../chapter11/04_akka_in_osgi.html">
                        <i class="fa fa-check"></i>
                        
                            <b>11.4.</b>
                        
                         Akka与OSGi
                    </a>
                
            
            
        </li>
    
        
        <li class="chapter " data-level="11.5" data-path="chapter11/05_incomplete_list_of_http_frameworks.html">
            
                
                    <a href="../chapter11/05_incomplete_list_of_http_frameworks.html">
                        <i class="fa fa-check"></i>
                        
                            <b>11.5.</b>
                        
                         部分HTTP框架名单
                    </a>
                
            
            
        </li>
    

            </ul>
            
        </li>
    


        
        <li class="divider"></li>
        <li>
            <a href="http://www.gitbook.io/" target="blank" class="gitbook-link">Published using GitBook</a>
        </li>
        
    </ul>
</div>

    <div class="book-body">
        <div class="body-inner">
            <div class="book-header">
    <!-- Actions Left -->
    <a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
    <a href="#" class="btn pull-left toggle-search" aria-label="Toggle search"><i class="fa fa-search"></i></a>
    
    <div id="font-settings-wrapper" class="dropdown pull-left">
        <a href="#" class="btn toggle-dropdown" aria-label="Toggle font settings"><i class="fa fa-font"></i>
        </a>
        <div class="dropdown-menu font-settings">
    <div class="dropdown-caret">
        <span class="caret-outer"></span>
        <span class="caret-inner"></span>
    </div>

    <div class="buttons">
        <button type="button" id="reduce-font-size" class="button size-2">A</button>
        <button type="button" id="enlarge-font-size" class="button size-2">A</button>
    </div>

    <div class="buttons font-family-list">
        <button type="button" data-font="0" class="button">Serif</button>
        <button type="button" data-font="1" class="button">Sans</button>
    </div>

    <div class="buttons color-theme-list">
        <button type="button" id="color-theme-preview-0" class="button size-3" data-theme="0">White</button>
        <button type="button" id="color-theme-preview-1" class="button size-3" data-theme="1">Sepia</button>
        <button type="button" id="color-theme-preview-2" class="button size-3" data-theme="2">Night</button>
    </div>
</div>

    </div>

    <!-- Actions Right -->
    
    <div class="dropdown pull-right">
        <a href="#" class="btn toggle-dropdown" aria-label="Toggle share dropdown"><i class="fa fa-share-alt"></i>
        </a>
        <div class="dropdown-menu font-settings dropdown-left">
            <div class="dropdown-caret">
                <span class="caret-outer"></span>
                <span class="caret-inner"></span>
            </div>
            <div class="buttons">
                <button type="button" data-sharing="twitter" class="button">Twitter</button>
                <button type="button" data-sharing="google-plus" class="button">Google</button>
                <button type="button" data-sharing="facebook" class="button">Facebook</button>
                <button type="button" data-sharing="weibo" class="button">Weibo</button>
                <button type="button" data-sharing="instapaper" class="button">Instapaper</button>
            </div>
        </div>
    </div>
    

    
    <a href="#" target="_blank" class="btn pull-right google-plus-sharing-link sharing-link" data-sharing="google-plus" aria-label="Share on Google Plus"><i class="fa fa-google-plus"></i></a>
    
    
    <a href="#" target="_blank" class="btn pull-right facebook-sharing-link sharing-link" data-sharing="facebook" aria-label="Share on Facebook"><i class="fa fa-facebook"></i></a>
    
    
    <a href="#" target="_blank" class="btn pull-right twitter-sharing-link sharing-link" data-sharing="twitter" aria-label="Share on Twitter"><i class="fa fa-twitter"></i></a>
    
    

    <!-- Title -->
    <h1>
        <i class="fa fa-circle-o-notch fa-spin"></i>
        <a href="../" >AKKA 2.3.6 Scala 文档</a>
    </h1>
</div>

            <div class="page-wrapper" tabindex="-1">
                <div class="page-inner">
                
                
                    <section class="normal" id="section-gitbook_132">
                    
                        <h1 id="tcp">使用TCP</h1>
<blockquote>
<p>注：本节未经校验，如有问题欢迎提issue</p>
</blockquote>
<p>贯穿本节的代码片段假定以下imports：</p>
<pre><code class="lang-scala"><span class="hljs-keyword">import</span> akka.actor.{ <span class="hljs-type">Actor</span>, <span class="hljs-type">ActorRef</span>, <span class="hljs-type">Props</span> }
<span class="hljs-keyword">import</span> akka.io.{ <span class="hljs-type">IO</span>, <span class="hljs-type">Tcp</span> }
<span class="hljs-keyword">import</span> akka.util.<span class="hljs-type">ByteString</span>
<span class="hljs-keyword">import</span> java.net.<span class="hljs-type">InetSocketAddress</span>
</code></pre>
<p>所有的Akka I/O API 都通过管理器对象来访问。当使用I/O API时，第一步是获得适当的管理器对象的引用。下面的代码演示如何获取<code>Tcp</code>管理器的引用。</p>
<pre><code class="lang-scala"><span class="hljs-keyword">import</span> akka.io.{ <span class="hljs-type">IO</span>, <span class="hljs-type">Tcp</span> }
<span class="hljs-keyword">import</span> context.system <span class="hljs-comment">// implicitly used by IO(Tcp)</span>

<span class="hljs-function"><span class="hljs-keyword">val</span> <span class="hljs-title">manager</span> =</span> <span class="hljs-type">IO</span>(<span class="hljs-type">Tcp</span>)
</code></pre>
<p>管理器是一个actor，来处理底层低级别 I/O 资源(selectors, channels)并为特定任务，如监听传入的连接，来实例化工作者。</p>
<h3 id="">连接</h3>
<pre><code class="lang-scala"><span class="hljs-class"><span class="hljs-keyword">object</span> <span class="hljs-title">Client</span> {</span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">props</span>(</span>remote: <span class="hljs-type">InetSocketAddress</span>, replies: <span class="hljs-type">ActorRef</span>) =
    <span class="hljs-type">Props</span>(classOf[<span class="hljs-type">Client</span>], remote, replies)
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span>(</span>remote: <span class="hljs-type">InetSocketAddress</span>, listener: <span class="hljs-type">ActorRef</span>) <span class="hljs-keyword">extends</span> <span class="hljs-type">Actor</span> {

  <span class="hljs-keyword">import</span> <span class="hljs-type">Tcp</span>._
  <span class="hljs-keyword">import</span> context.system

  <span class="hljs-type">IO</span>(<span class="hljs-type">Tcp</span>) ! <span class="hljs-type">Connect</span>(remote)

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">receive</span> =</span> {
    <span class="hljs-keyword">case</span> <span class="hljs-type">CommandFailed</span>(_: <span class="hljs-type">Connect</span>) =&gt;
      listener ! <span class="hljs-string">"connect failed"</span>
      context stop self

    <span class="hljs-keyword">case</span> c @ <span class="hljs-type">Connected</span>(remote, local) =&gt;
      listener ! c
      <span class="hljs-function"><span class="hljs-keyword">val</span> <span class="hljs-title">connection</span> =</span> sender()
      connection ! <span class="hljs-type">Register</span>(self)
      context become {
        <span class="hljs-keyword">case</span> data: <span class="hljs-type">ByteString</span> =&gt;
          connection ! <span class="hljs-type">Write</span>(data)
        <span class="hljs-keyword">case</span> <span class="hljs-type">CommandFailed</span>(w: <span class="hljs-type">Write</span>) =&gt;
          <span class="hljs-comment">// O/S buffer was full</span>
          listener ! <span class="hljs-string">"write failed"</span>
        <span class="hljs-keyword">case</span> <span class="hljs-type">Received</span>(data) =&gt;
          listener ! data
        <span class="hljs-keyword">case</span> <span class="hljs-string">"close"</span> =&gt;
          connection ! <span class="hljs-type">Close</span>
        <span class="hljs-keyword">case</span> _: <span class="hljs-type">ConnectionClosed</span> =&gt;
          listener ! <span class="hljs-string">"connection closed"</span>
          context stop self
      }
  }
}
</code></pre>
<p>连接到一个远程地址的第一步是将<code>Connect</code>消息发送到 TCP 管理器 ；除了上面所示的简单形式外，还可以指定要绑定的本地<code>InetSocketAddress</code>和要应用的套接字选项列表。</p>
<blockquote>
<p>注意</p>
<p>SO_NODELAY (Windows下是TCP_NODELAY）套接字选项在Akka中默认为 true，独立于操作系统的默认设置。此设置禁用Nagle算法，大大提高对于大多数应用程序的延迟。此设置可以通过在<code>Connect</code>消息的套接字选项的列表中加入<code>SO.TcpNoDelay(false)</code>来重写。</p>
</blockquote>
<p>TCP 管理器然后将要么回复<code>CommandFailed</code>，要么产生一个内部的actor代表新的连接。这位新actor然后将向<code>Connect</code>消息的原始发送人发送一个<code>Connected</code>消息。</p>
<p>为了激活新的连接，<code>Register</code>消息必须发送到连接actor，通知它谁将从套接字接收数据。此步骤完成之前不能使用连接，而且还有一个内部超时，在此之后如果没有收到<code>Register</code>消息，连接actor将关闭自身。</p>
<p>连接actor观察注册的处理程序，并在处理者终止时关闭连接，从而清理与该连接相关的所有内部资源。</p>
<p>上面的示例中actor使用<code>become</code>来从无连接状态切换到已连接状态，演示那种状态下被观察到的命令和事件。关于<code>CommandFailed</code>参见下文的讨论——<a href="#throttling-reads-and-writes">读写限流</a>。<code>ConnectionClosed</code>是一个特质，它标志着不同的连接关闭事件。最后一行中以同样的方式处理所有的连接关闭事件。有可能监听更多的细粒度的连接关闭事件，请参阅下面的<a href="#closing-connections">关闭连接</a>。</p>
<h3 id="">接受连接</h3>
<pre><code class="lang-scala"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Server</span> <span class="hljs-keyword"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">Actor</span> {</span>

  <span class="hljs-keyword">import</span> <span class="hljs-type">Tcp</span>._
  <span class="hljs-keyword">import</span> context.system

  <span class="hljs-type">IO</span>(<span class="hljs-type">Tcp</span>) ! <span class="hljs-type">Bind</span>(self, <span class="hljs-keyword">new</span> <span class="hljs-type">InetSocketAddress</span>(<span class="hljs-string">"localhost"</span>, <span class="hljs-number">0</span>))

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">receive</span> =</span> {
    <span class="hljs-keyword">case</span> b @ <span class="hljs-type">Bound</span>(localAddress) =&gt;
      <span class="hljs-comment">// do some logging or setup ...</span>

    <span class="hljs-keyword">case</span> <span class="hljs-type">CommandFailed</span>(_: <span class="hljs-type">Bind</span>) =&gt; context stop self

    <span class="hljs-keyword">case</span> c @ <span class="hljs-type">Connected</span>(remote, local) =&gt;
      <span class="hljs-function"><span class="hljs-keyword">val</span> <span class="hljs-title">handler</span> =</span> context.actorOf(<span class="hljs-type">Props</span>[<span class="hljs-type">SimplisticHandler</span>])
      <span class="hljs-function"><span class="hljs-keyword">val</span> <span class="hljs-title">connection</span> =</span> sender()
      connection ! <span class="hljs-type">Register</span>(handler)
  }

}
</code></pre>
<p>要创建一个 TCP 服务器并监听入站连接，需要发送一个<code>Bind</code>命令到 TCP 管理器。这将指示 TCP 管理器来侦听一个特定<code>InetSocketAddress</code>的 TCP 连接；可将端口指定为 0来绑定一个随机端口。</p>
<p>发送<code>Bind</code>消息的actor将收到<code>Bound</code>消息，表示服务器已准备好接收传入的连接 ；此消息还包含实际绑定到套接字的<code>InetSocketAddress</code>（即解析号的 IP 地址和正确的端口号）。</p>
<p>从这个点开始，处理连接的过程与传出连接是相同的。该示例演示了，当发送<code>Register</code>消息时，来自某个连接的读取可以委派给另一位被指定处理程序的actor。写操作可以从系统中任何一个actor发送到连接actor （即发送<code>Connected</code>消息的actor）。简单化的处理程序定义如下：</p>
<pre><code class="lang-scala"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SimplisticHandler</span> <span class="hljs-keyword"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">Actor</span> {</span>
  <span class="hljs-keyword">import</span> <span class="hljs-type">Tcp</span>._
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">receive</span> =</span> {
    <span class="hljs-keyword">case</span> <span class="hljs-type">Received</span>(data) =&gt; sender() ! <span class="hljs-type">Write</span>(data)
    <span class="hljs-keyword">case</span> <span class="hljs-type">PeerClosed</span>     =&gt; context stop self
  }
}
</code></pre>
<p>在发送时考虑到失败可能性的更完整示例，请参阅下面的<a href="#throttling-reads-and-writes">读写限流</a>。</p>
<p>对传出连接的唯一区别是内部actor管理监听端口 —— <code>Bound</code>消息的发件人 —— 观察在<code>Bind</code>消息中被指定为<code>Connected</code>消息接收者的那个actor。那个actor终止时监听端口将会封闭，与它相关的所有资源将都被释放 ；在这一点上，现有连接不会被终止。</p>
<h3 id="">关闭连接</h3>
<p>可以通过发送<code>Close</code>, <code>ConfirmedClose</code>或<code>Abort</code>之一的命令到连接actor关闭连接。</p>
<p>通过发送<code>FIN</code>消息，<code>Close</code>将关闭该连接，但没有等待远端的确认。挂起的写操作将被执行(flush)。如果关闭成功, 监听器将收到<code>Closed</code>通知。</p>
<p>通过发送<code>FIN</code>消息，<code>ConfirmedClose</code>将关闭发送方的连接，但仍会收到数据直到远端也关闭连接。挂起的写操作将被执行(flush)。如果关闭成功, 监听器将收到<code>ConfirmedClosed</code>通知。</p>
<p>通过发送<code>RST</code>消息到远端，<code>Abort</code>将立即终止连接。挂起的写操作将不会被执行(flush)。如果关闭成功, 监听器将收到<code>Aborted</code>通知。</p>
<p>如果该连接被远端关闭，监听器将收到<code>PeerClosed</code>通知。默认情况下，该连接然后也会被本端自动关闭。要支持半闭连接，请将<code>Register</code>消息的<code>keepOpenOnPeerClosed</code>成员设置为 <code>true</code>，在此情况下连接将保持打开状态，直到它接收到一个上文介绍的关闭命令。</p>
<p>每当一个错误发生并迫使该连接关闭时，<code>ErrorClosed</code>将发送到监听器。</p>
<p>所有关闭通知都是<code>ConnectionClosed</code>的子类型，所以不需要细粒度事件的监听器可以以相同的方式处理所有的关闭事件。</p>
<h3 id="">写入一个连接</h3>
<p>一旦连接建立，数据可以从任何actor通过 <code>Tcp.WriteCommand</code> 的形式发送给连接。<code>Tcp.WriteCommand</code> 是一个抽象类，有三个具体的实现：</p>
<ul>
<li><p>Tcp.Write</p>
<p>最简单的 <code>WriteCommand</code> 实现，它包装了一个 <code>ByteString</code> 实例和一个&quot;ack&quot;事件。一个<code>ByteString</code> （如在<a href="05_io.html#bytestring_scala">这一节</a>解释的） 建模了一个或多个不可变的内存数据块，最大可达2GB (2^31个字节）。</p>
</li>
<li><p>Tcp.WriteFile</p>
<p>如果你想要从一个文件发送&quot;原始&quot;数据，你可以高效地使用<code>Tcp.WriteFile</code>命令。它将允许你指定磁盘上一块（连续的）字节在连接中发送，而无需首先将其加载到JVM内存中。<code>Tcp.WriteFile</code>可以&quot;hold&quot;大于2 GB的数据和并根据需要提供&quot;ack&quot;事件。</p>
</li>
<li><p>Tcp.CompoundWrite</p>
<p>有时你可能想要组（或交错）若干 <code>Tcp.Write</code>和/或 <code>Tcp.WriteFile</code>命令到一个原子写命令，一次写入连接。<code>Tcp.CompoundWrite</code>允许你做到这一点，并提供三个优点：</p>
<ol>
<li>如下节中所述，TCP连接actor一次只能处理一个单一写命令。通过组合几个写到一个<code>CompoundWrite</code>，你可以让他们通过连接发送，并拥有最低开销，也无需像&quot;一勺勺喂&quot;一样通过<em>基于ACK</em>的消息协议发送给连接actor。</li>
<li>因为<code>WriteCommand</code>是原子的，你可以确定没有其他actor可以在你的写序列中&quot;注入&quot;其他写操作，如果你将它们组合为一个单一的 <code>CompoundWrite</code>。在多个actor写入相同连接的情况下，这可以是一个重要的特性，通过别的方式很难实现。</li>
<li><code>CompoundWrite</code>的&quot;子写操作&quot;是普通的<code>Write</code>或<code>WriteFile</code>命令，其本身可以请求&quot;ack&quot;事件。这些ACK会在相应的&quot;子写操作&quot;被完成时尽快发送。这允许你将附加多个ACK到<code>Write</code>或 <code>WriteFile</code>（通过组合一个要求ACK的空写）或让连接actor通过在任意点发送中间ACK确认<code>CompoundWrite</code>的传输进度。</li>
</ol>
</li>
</ul>
<h3 id="a-namethrottling-reads-and-writesa"><a name="throttling-reads-and-writes"></a>读写限流</h3>
<p>TCP 连接actor的基本模型是它有没有内部缓冲 （即它一次只能处理一个写操作，意味着它可以缓冲一次写入，直到写入全部被传递到操作系统内核）。写入和读取的拥塞情况需要在用户级别上处理。</p>
<p>高压写有三种操作模式</p>
<ul>
<li><em>基于ACK</em>：每个<code>Write</code>命令装载一个任意的对象，并且如果该对象不是<code>Tcp.NoAck</code>，则它将在所有包含数据成功写入到套接字后返回给<code>Write</code>的发送人。如果收到此确认之前没有启动其他写操作，则由于缓冲区重用没有失败可以发生。</li>
<li><em>基于NACK</em>：在前一个写操作完成之前，每一个新到达的写都将被回复一个包含失败写操作的<code>CommandFailed</code>消息。仅仅依靠这种机制要求实现协议容忍跳过写操作 (例如如果每个写入操作自身是一个有效的消息，并且不要求所有都送达）。通过在连接激活阶段的<code>Register</code>消息中设置<code>useResumeWriting</code>标志为 <code>false</code>来启用此模式。</li>
<li><em>基于NACK与写挂起</em>： 这种模式非常类似于基于NACK的模式，但一旦一次写操作失败，则没有进一步写操作会成功直到接收到<code>ResumeWriting</code>消息。一旦上一次接受的写入操作完成，将由一个<code>WritingResumed</code>消息回答此消息。如果驱动连接的actor实现缓冲，并在等到<code>WritingResumed</code>信号后重发NACK标记的消息，则每个消息确切地只传递一次给网络套接字。</li>
</ul>
<p>这些高压写模型在下面的示例中进行了完整演示 （除了相当专业化的第二个）。完整的相关资源可以在<a href="http://github.com/akka/akka/tree/v2.3.6/akka-docs/rst/scala/code/docs/io/EchoServer.scala" target="_blank">github</a>上获得。</p>
<p>高压读有两种操作模式</p>
<ul>
<li><em>推送读</em>： 在此模式下连接actor一旦收到<code>Received</code>事件，就向注册的读actor发送传入的数据。每当读actor想要通知到远程 TCP 端点压力过大时，它可以发送 <code>SuspendReading</code>消息到连接actor表示它想要暂停接收新数据。没有收到<code>Received</code>事件直到<code>ResumeReading</code>被发送，表示接收actor又准备好了。</li>
<li><em>拉取读</em>： 发送一个<code>Received</code>事件后连接actor会自动挂起从套接字接受数据，直到读actor发送一个<code>ResumeReading</code>信息，作为信号表示它准备好要处理更多的输入数据。因此新的数据是通过发送<code>ResumeReading</code>消息从连接&quot;拉&quot;到的。</li>
</ul>
<blockquote>
<p>注意</p>
<p>显而易见，所有这些流控制方案只能在一对写者/读者和一个连接actor之间工作；一旦多个actor发送写命令到一个单独的连接，可以会出现不一致的结果。</p>
</blockquote>
<h3 id="ack">基于ACK的高压写</h3>
<p>为下面示例能恰当的工作，很重要的一点是当远端关闭其写入时，要配置连接保持半打开状态： 这允许 <code>EchoHandler</code>在连接完全关闭之前将所有未提交数据写到客户端。它是使用连接激活的标志启用的 （观察<code>Register</code>消息）：</p>
<pre><code class="lang-scala"><span class="hljs-keyword">case</span> <span class="hljs-type">Connected</span>(remote, local) =&gt;
  log.info(<span class="hljs-string">"received connection from {}"</span>, remote)
  <span class="hljs-function"><span class="hljs-keyword">val</span> <span class="hljs-title">handler</span> =</span> context.actorOf(<span class="hljs-type">Props</span>(handlerClass, sender(), remote))
  sender() ! <span class="hljs-type">Register</span>(handler, keepOpenOnPeerClosed = <span class="hljs-literal">true</span>)
</code></pre>
<p>有了这样的让我们深入看下处理程序：</p>
<pre><code class="lang-scala">  <span class="hljs-comment">// storage omitted ...</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SimpleEchoHandler</span>(</span>connection: <span class="hljs-type">ActorRef</span>, remote: <span class="hljs-type">InetSocketAddress</span>)
  <span class="hljs-keyword">extends</span> <span class="hljs-type">Actor</span> <span class="hljs-keyword">with</span> <span class="hljs-type">ActorLogging</span> {

  <span class="hljs-keyword">import</span> <span class="hljs-type">Tcp</span>._

  <span class="hljs-comment">// sign death pact: this actor terminates when connection breaks</span>
  context watch connection

  <span class="hljs-keyword">case</span> <span class="hljs-class"><span class="hljs-keyword">object</span> <span class="hljs-title">Ack</span> <span class="hljs-keyword"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">Event</span>
</span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">receive</span> =</span> {
    <span class="hljs-keyword">case</span> <span class="hljs-type">Received</span>(data) =&gt;
      buffer(data)
      connection ! <span class="hljs-type">Write</span>(data, <span class="hljs-type">Ack</span>)

      context.become({
        <span class="hljs-keyword">case</span> <span class="hljs-type">Received</span>(data) =&gt; buffer(data)
        <span class="hljs-keyword">case</span> <span class="hljs-type">Ack</span>            =&gt; acknowledge()
        <span class="hljs-keyword">case</span> <span class="hljs-type">PeerClosed</span>     =&gt; closing = <span class="hljs-literal">true</span>
      }, discardOld = <span class="hljs-literal">false</span>)

    <span class="hljs-keyword">case</span> <span class="hljs-type">PeerClosed</span> =&gt; context stop self
  }

  <span class="hljs-comment">// storage omitted ...</span>
}
</code></pre>
<p>原理很简单： 当写如一大块数据后，总是在发送下一个块之前等待<code>Ack</code>发送回来。在等待期间，我们切换行为来缓冲新传入的数据。所使用的辅助函数有点长但并不复杂：</p>
<pre><code class="lang-scala"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">buffer</span>(</span>data: <span class="hljs-type">ByteString</span>): <span class="hljs-type">Unit</span> = {
  storage :+= data
  stored += data.size

  <span class="hljs-keyword">if</span> (stored &gt; maxStored) {
    log.warning(s<span class="hljs-string">"drop connection to [$remote] (buffer overrun)"</span>)
    context stop self

  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (stored &gt; highWatermark) {
    log.debug(s<span class="hljs-string">"suspending reading"</span>)
    connection ! <span class="hljs-type">SuspendReading</span>
    suspended = <span class="hljs-literal">true</span>
  }
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">acknowledge</span>(</span>): <span class="hljs-type">Unit</span> = {
  require(storage.nonEmpty, <span class="hljs-string">"storage was empty"</span>)

  <span class="hljs-function"><span class="hljs-keyword">val</span> <span class="hljs-title">size</span> =</span> storage(<span class="hljs-number">0</span>).size
  stored -= size
  transferred += size

  storage = storage drop <span class="hljs-number">1</span>

  <span class="hljs-keyword">if</span> (suspended &amp;&amp; stored &lt; lowWatermark) {
    log.debug(<span class="hljs-string">"resuming reading"</span>)
    connection ! <span class="hljs-type">ResumeReading</span>
    suspended = <span class="hljs-literal">false</span>
  }

  <span class="hljs-keyword">if</span> (storage.isEmpty) {
    <span class="hljs-keyword">if</span> (closing) context stop self
    <span class="hljs-keyword">else</span> context.unbecome()
  } <span class="hljs-keyword">else</span> connection ! <span class="hljs-type">Write</span>(storage(<span class="hljs-number">0</span>), <span class="hljs-type">Ack</span>)
}
</code></pre>
<p>最有趣的部分也许是最后一行： 一个<code>Ack</code>从缓冲区中删除最旧的数据块，如果这是最后一个块则我们要么关闭连接 （如果同行已经关闭了它的一半）要么返回到空闲的行为；不然我们就发送下一个缓冲块，并等待下一个<code>Ack</code>。</p>
<p>高压也可以传播，穿过读侧回到连接另一端的写侧，通过将<code>SuspendReading</code>命令发送到连接actor。这将导致不再从套接字读取任何数据 （尽管这会延迟发生，因为它需要一些时间，直到连接actor处理这个命令，因此适当的头部缓冲区应该出现) ，反过来这将导致我们这一端的操作系统内核缓冲区填满，然后 TCP 窗口机制将停止远端写，填满其写入缓冲区，直到最后另一端的写者无法推如任何数据到套接字中了。这是端到端高压如何在跨 TCP 连接实现的。</p>
<h3 id="nack">带有挂起的基于NACK高压写</h3>
<pre><code class="lang-scala"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EchoHandler</span>(</span>connection: <span class="hljs-type">ActorRef</span>, remote: <span class="hljs-type">InetSocketAddress</span>)
  <span class="hljs-keyword">extends</span> <span class="hljs-type">Actor</span> <span class="hljs-keyword">with</span> <span class="hljs-type">ActorLogging</span> {

  <span class="hljs-keyword">import</span> <span class="hljs-type">Tcp</span>._

  <span class="hljs-keyword">case</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Ack</span>(</span>offset: <span class="hljs-type">Int</span>) <span class="hljs-keyword">extends</span> <span class="hljs-type">Event</span>

  <span class="hljs-comment">// sign death pact: this actor terminates when connection breaks</span>
  context watch connection

  <span class="hljs-comment">// start out in optimistic write-through mode</span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">receive</span> =</span> writing

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">writing</span>:</span> <span class="hljs-type">Receive</span> = {
    <span class="hljs-keyword">case</span> <span class="hljs-type">Received</span>(data) =&gt;
      connection ! <span class="hljs-type">Write</span>(data, <span class="hljs-type">Ack</span>(currentOffset))
      buffer(data)

    <span class="hljs-keyword">case</span> <span class="hljs-type">Ack</span>(ack) =&gt;
      acknowledge(ack)

    <span class="hljs-keyword">case</span> <span class="hljs-type">CommandFailed</span>(<span class="hljs-type">Write</span>(_, <span class="hljs-type">Ack</span>(ack))) =&gt;
      connection ! <span class="hljs-type">ResumeWriting</span>
      context become buffering(ack)

    <span class="hljs-keyword">case</span> <span class="hljs-type">PeerClosed</span> =&gt;
      <span class="hljs-keyword">if</span> (storage.isEmpty) context stop self
      <span class="hljs-keyword">else</span> context become closing
  }

  <span class="hljs-comment">// buffering ...</span>

  <span class="hljs-comment">// closing ...</span>

  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">postStop</span>(</span>): <span class="hljs-type">Unit</span> = {
    log.info(s<span class="hljs-string">"transferred $transferred bytes from/to [$remote]"</span>)
  }

  <span class="hljs-comment">// storage omitted ...</span>
}
  <span class="hljs-comment">// storage omitted ...</span>
</code></pre>
<p>这里的原则是保持写，直到接收到一个<code>CommandFailed</code>，仅使用确认来修剪重发缓冲区。当收到了此类故障时，过渡到一个不同的处理状态，并处理重发队列中的所有数据：</p>
<pre><code class="lang-scala"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">buffering</span>(</span>nack: <span class="hljs-type">Int</span>): <span class="hljs-type">Receive</span> = {
  <span class="hljs-keyword">var</span> toAck = <span class="hljs-number">10</span>
  <span class="hljs-keyword">var</span> peerClosed = <span class="hljs-literal">false</span>

  {
    <span class="hljs-keyword">case</span> <span class="hljs-type">Received</span>(data)         =&gt; buffer(data)
    <span class="hljs-keyword">case</span> <span class="hljs-type">WritingResumed</span>         =&gt; writeFirst()
    <span class="hljs-keyword">case</span> <span class="hljs-type">PeerClosed</span>             =&gt; peerClosed = <span class="hljs-literal">true</span>
    <span class="hljs-keyword">case</span> <span class="hljs-type">Ack</span>(ack) <span class="hljs-keyword">if</span> ack &lt; nack =&gt; acknowledge(ack)
    <span class="hljs-keyword">case</span> <span class="hljs-type">Ack</span>(ack) =&gt;
      acknowledge(ack)
      <span class="hljs-keyword">if</span> (storage.nonEmpty) {
        <span class="hljs-keyword">if</span> (toAck &gt; <span class="hljs-number">0</span>) {
          <span class="hljs-comment">// stay in ACK-based mode for a while</span>
          writeFirst()
          toAck -= <span class="hljs-number">1</span>
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-comment">// then return to NACK-based again</span>
          writeAll()
          context become (<span class="hljs-keyword">if</span> (peerClosed) closing <span class="hljs-keyword">else</span> writing)
        }
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (peerClosed) context stop self
      <span class="hljs-keyword">else</span> context become writing
  }
}
</code></pre>
<p>应指出的是当前缓冲的所有写操作，在进入这种状态时也都已被发送到连接actor，这意味着<code>ResumeWriting</code>消息是在那些写操作之后入队的，导致接收所有突出的<code>CommandFailed</code>消息 （在这种状态被忽略）在收到<code>WritingResumed</code>信号之前。后一种消息只在内部排队的写操作完全完成时，由连接actor发送，意味着一个后续的写操作不会失败。这被<code>EchoHandler</code>用来为头十个写操作切换到基于ACK的方式，在一次失败后和恢复到乐观完全写行为之前。</p>
<pre><code class="lang-scala"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">closing</span>:</span> <span class="hljs-type">Receive</span> = {
  <span class="hljs-keyword">case</span> <span class="hljs-type">CommandFailed</span>(_: <span class="hljs-type">Write</span>) =&gt;
    connection ! <span class="hljs-type">ResumeWriting</span>
    context.become({

      <span class="hljs-keyword">case</span> <span class="hljs-type">WritingResumed</span> =&gt;
        writeAll()
        context.unbecome()

      <span class="hljs-keyword">case</span> ack: <span class="hljs-type">Int</span> =&gt; acknowledge(ack)

    }, discardOld = <span class="hljs-literal">false</span>)

  <span class="hljs-keyword">case</span> <span class="hljs-type">Ack</span>(ack) =&gt;
    acknowledge(ack)
    <span class="hljs-keyword">if</span> (storage.isEmpty) context stop self
}
</code></pre>
<p>仍在发送所有数据时关闭连接，相比基于ACK的办法涉及更多内容：这个想法是，总是发送所有未完成的消息和确认所有成功的写操作，并且如果发生故障则切换行为等待<code>WritingResumed</code>事件并重新开始。</p>
<p>辅助函数非常类似于基于 ACK 的例子：</p>
<pre><code class="lang-scala"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">buffer</span>(</span>data: <span class="hljs-type">ByteString</span>): <span class="hljs-type">Unit</span> = {
  storage :+= data
  stored += data.size

  <span class="hljs-keyword">if</span> (stored &gt; maxStored) {
    log.warning(s<span class="hljs-string">"drop connection to [$remote] (buffer overrun)"</span>)
    context stop self

  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (stored &gt; highWatermark) {
    log.debug(s<span class="hljs-string">"suspending reading at $currentOffset"</span>)
    connection ! <span class="hljs-type">SuspendReading</span>
    suspended = <span class="hljs-literal">true</span>
  }
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">acknowledge</span>(</span>ack: <span class="hljs-type">Int</span>): <span class="hljs-type">Unit</span> = {
  require(ack == storageOffset, s<span class="hljs-string">"received ack $ack at $storageOffset"</span>)
  require(storage.nonEmpty, s<span class="hljs-string">"storage was empty at ack $ack"</span>)

  <span class="hljs-function"><span class="hljs-keyword">val</span> <span class="hljs-title">size</span> =</span> storage(<span class="hljs-number">0</span>).size
  stored -= size
  transferred += size

  storageOffset += <span class="hljs-number">1</span>
  storage = storage drop <span class="hljs-number">1</span>

  <span class="hljs-keyword">if</span> (suspended &amp;&amp; stored &lt; lowWatermark) {
    log.debug(<span class="hljs-string">"resuming reading"</span>)
    connection ! <span class="hljs-type">ResumeReading</span>
    suspended = <span class="hljs-literal">false</span>
  }
}
</code></pre>
<h3 id="">带有拉取模式高压写</h3>
<p>当使用拉取读时，来自套接字的数据在可用时会被尽快发送到actor。在前面的Echo服务器示例中的情况下，这意味着我们需要维护一个传入数据缓冲区来保持它，因为写入的速度可能会低于新数据到达的速度。</p>
<p>在拉取模式下这个缓冲区可以完全消除，如下面的代码段所示：</p>
<pre><code class="lang-scala"><span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">preStart</span>:</span> <span class="hljs-type">Unit</span> = connection ! <span class="hljs-type">ResumeReading</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">receive</span> =</span> {
  <span class="hljs-keyword">case</span> <span class="hljs-type">Received</span>(data) =&gt; connection ! <span class="hljs-type">Write</span>(data, <span class="hljs-type">Ack</span>)
  <span class="hljs-keyword">case</span> <span class="hljs-type">Ack</span>            =&gt; connection ! <span class="hljs-type">ResumeReading</span>
}
</code></pre>
<p>这里的想法是，直到以前写操作已被连接actor完全确认才恢复读。每个拉取模式连接actor都是从挂起状态开始。要启动数据流我们发送一个 <code>ResumeReading</code> 到<code>preStart</code>方法告诉连接actor我们准备好接收第一个块数据了。因为我们只在先前的数据块已经被完全写入的情况下才恢复读，所以就没有必要维持一个缓冲区。</p>
<p>要对一个出站连接启用拉取读,<code>Connect</code>的 <code>pullMode</code> 参数应被设置为 <code>true</code>：</p>
<pre><code class="lang-scala"><span class="hljs-type">IO</span>(<span class="hljs-type">Tcp</span>) ! <span class="hljs-type">Connect</span>(listenAddress, pullMode = <span class="hljs-literal">true</span>)
</code></pre>
<h5 id="">入站连接的拉取读模式</h5>
<p>前一节演示了如何为出站连接启用拉取读模式，但也可能创建一个监听器actor具有这种读模式，通过设置 <code>Bind</code> 命令的 <code>pullMode</code> 参数设置为 <code>true</code>：</p>
<pre><code class="lang-scala"><span class="hljs-type">IO</span>(<span class="hljs-type">Tcp</span>) ! <span class="hljs-type">Bind</span>(self, <span class="hljs-keyword">new</span> <span class="hljs-type">InetSocketAddress</span>(<span class="hljs-string">"localhost"</span>, <span class="hljs-number">0</span>), pullMode = <span class="hljs-literal">true</span>)
</code></pre>
<p>此设置的影响之一是此监听器actor所接受的所有连接将都使用拉取读模式。</p>
<p>此设置的另一个影响是除了所有的入站连接被设置为拉取读模式，接受连接也变为基于拉取的了。这意味着在处理一个（或多个） <code>Connected</code>事件后监听器actor一定要通过发送它一条 <code>ResumeAccepting</code> 消息来恢复。</p>
<p>拉取模式中的侦听器actor以挂起方式开始来接受连接，在绑定成功后必须发送<code>ResumeAccepting</code>命令到监听actor：</p>
<pre><code class="lang-scala"><span class="hljs-keyword">case</span> <span class="hljs-type">Bound</span>(localAddress) =&gt;
  <span class="hljs-comment">// Accept connections one by one</span>
  sender ! <span class="hljs-type">ResumeAccepting</span>(batchSize = <span class="hljs-number">1</span>)
  context.become(listening(sender))
</code></pre>
<p>在处理传入的连接后，我们需要再一次恢复接收：</p>
<pre><code class="lang-scala"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">listening</span>(</span>listener: <span class="hljs-type">ActorRef</span>): <span class="hljs-type">Receive</span> = {
  <span class="hljs-keyword">case</span> <span class="hljs-type">Connected</span>(remote, local) =&gt;
    <span class="hljs-function"><span class="hljs-keyword">val</span> <span class="hljs-title">handler</span> =</span> context.actorOf(<span class="hljs-type">Props</span>(classOf[<span class="hljs-type">PullEcho</span>], sender))
    sender ! <span class="hljs-type">Register</span>(handler, keepOpenOnPeerClosed = <span class="hljs-literal">true</span>)
    listener ! <span class="hljs-type">ResumeAccepting</span>(batchSize = <span class="hljs-number">1</span>)
}
</code></pre>
<p><code>ResumeAccepting</code> 接受一个 <code>batchSize</code> 参数，指定在需要下一个 <code>ResumeAccepting</code> 消息恢复处理新的连接之前，接受多少新的连接。</p>

                    
                    </section>
                
                
                </div>
            </div>
        </div>

        
        <a href="../chapter5/05_io.html" class="navigation navigation-prev " aria-label="Previous page: I/O"><i class="fa fa-angle-left"></i></a>
        
        
        <a href="../chapter5/07_using_udp.html" class="navigation navigation-next " aria-label="Next page: 使用UDP"><i class="fa fa-angle-right"></i></a>
        
    </div>
</div>

        
<script src="../gitbook/app.js"></script>

    
    <script src="https://cdn.mathjax.org/mathjax/2.4-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
    

    
    <script src="../gitbook/plugins/gitbook-plugin-mathjax/plugin.js"></script>
    

<script>
require(["gitbook"], function(gitbook) {
    var config = {"fontSettings":{"theme":null,"family":"sans","size":2}};
    gitbook.start(config);
});
</script>

        
    </body>
    
</html>
